﻿#region copyright
//<copyright>
// Copyright(C) 2012 TrackerRealm Corporation
// This file is part of the open source project - Jazz. http://jazz.codeplex.com
// 
// Jazz is open software: you can redistribute it and/or modify it 
// under the terms of the GNU Affero General Public License (AGPL) as published by 
// the Free Software Foundation, version 3 of the License.
// 
// Jazz is distributed in the hope that it will be useful, 
// but WITHOUT ANY WARRANTY; without even the implied warranty 
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
//  See the GNU Affero General Public License (AGPL) for more details.
// 
// You should have received a copy of the GNU General Public 
// License along with Jazz.  If not, see <http://www.gnu.org/licenses/>.
//
// REMOVAL OF THIS NOTICE IS VIOLATION OF THE COPYRIGHT. 
//</copyright>
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Reflection;

namespace TrackerRealm.Jazz.Client
{
    /// <summary>
    /// 
    /// </summary>
    public class StateTable : IEnumerable<StateTableEntry>, ICollection<StateTableEntry>
    {
        //public static StatesCollection Empty = new StatesTransitionCollection(jState.EmptyArray, jState.Empty);
        private StateTableEntry[] statesArray;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="jclass"></param>
        /// <returns></returns>
        internal static StateTable Create(jClass jclass)
        {
            return new StateTable(jclass);
        }
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="jclass"></param>
        private StateTable(jClass jclass)
        {
            List<StateTableEntry> list = new List<StateTableEntry>(16);
            foreach (jState state in jclass.States)
            {
                object[] attrArray = state.MethodInfo.GetCustomAttributes(typeof(StateToAttribute), false);
                foreach (StateToAttribute transitionAttr in attrArray)
                {
                    list.Add(StateTableEntry.Create(jclass, state, jclass.States.Find(transitionAttr.ToState), transitionAttr.Via));
                }
            }
            this.statesArray = list.ToArray();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public StateTableEntry Find(string name)
        {
            StateTableEntry state = this.statesArray.FirstOrDefault(s => s.Name == name);
            if (state == null) return StateTableEntry.Empty;
            return state;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="name"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        public bool TryFind(string name, out StateTableEntry state)
        {
            state = this.statesArray.FirstOrDefault(s => s.Name == name);
            if (state == null) return false;
            return true;
        }
        /// <summary>
        /// 
        /// </summary>
        public jState StartState
        {
            get;
            private set;
        }
        #region IEnumerable<jState> Members
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public IEnumerator<StateTableEntry> GetEnumerator()
        {
            return ((IEnumerable<StateTableEntry>)this.statesArray).GetEnumerator();
        }

        #endregion

        #region IEnumerable Members
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        #endregion

        #region ICollection<jRole> Members
        /// <summary>
        /// 
        /// </summary>
        /// <param name="item"></param>
        public void Add(StateTableEntry item)
        {
            throw new InvalidOperationException();
        }
        /// <summary>
        /// 
        /// </summary>
        public void Clear()
        {
            throw new InvalidOperationException();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public bool Contains(StateTableEntry item)
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="array"></param>
        /// <param name="arrayIndex"></param>
        public void CopyTo(StateTableEntry[] array, int arrayIndex)
        {
            this.statesArray.CopyTo(array, arrayIndex);
        }
        /// <summary>
        /// 
        /// </summary>
        public int Count
        {
            get { return this.statesArray.Length; }
        }
        /// <summary>
        /// 
        /// </summary>
        public bool IsReadOnly
        {
            get { return true; }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public bool Remove(StateTableEntry item)
        {
            throw new InvalidOperationException();
        }

        #endregion
    }
}
